/*******************************************************************************
 * Copyright 2011 @ Kapil Viren Ahuja
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package com.kapil.framework.concurrent.impl;

import com.kapil.framework.concurrent.IBroker;
import com.kapil.framework.concurrent.IProducer;

/**
 * <p>
 * This class provided basic and common functionality for any class that wants to implement {@link IProducer} and
 * provide the following functionalities:
 * </p>
 * 
 * <p>
 * This class allows the {@link Thread} until the sub-class sets the {@link IBroker#isProducing()} 
 * to <code>FALSE</code>
 * </p>
 * 
 * 
 * @author Kapil Viren Ahuja
 * 
 * @param <V>
 */
public abstract class AbstractProducer<V> implements IProducer<V>
{
    private IBroker<V> broker;


    /**
     * Default Constructor that initializes the Producer with a name and {@link IBroker}.
     * 
     * @param name
     * @param broker
     */
    public AbstractProducer(IBroker<V> broker)
    {
        this.broker = broker;
    }


    /**
     * Function that is invoked when the {@link Thread} starts and is the entry point for the functionality.
     * 
     */
    public void run()
    {
        doPopulateBroker();

        // In most cases, the concrete implementation should not worry about stop producing, and hence this
        // should be executed here, but in some cases the concrete implementation may stop the production
        if (this.broker.isProducing())
        {
            this.broker.stopProducing();
        }
        
        System.out.println("Producer is shutting down");
    }


    /**
     * Add the data into the {@link IBroker}.
     * 
     * @param data
     */
    public void updateBroker(V data)
    {
        try
        {
            this.broker.put(data);
        }
        catch (InterruptedException iex)
        {
            iex.printStackTrace();
        }
    }


    /**
     * This is an abstract method that allows any class extending this class to write to perform core logic.
     * 
     * @param data
     */
    protected abstract void doPopulateBroker();
}
